/*
 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"

#define SYS_DELAY_TICKS 200
#define TASK_STACK_SIZE 4096
#define TASK_PRIO 25

#define DEFAULT_VREF 1100                        // 默认参考电压，单位mV
static esp_adc_cal_characteristics_t *adc_chars; // 分配内存使用

#define myADC_heat_sensitive_channel ADC_CHANNEL_6      // GPIO34 光敏传感器Ao输入
#define AD_Value1_Channnel myADC_heat_sensitive_channel // 重新定义一个, 为例后续更好的更改

#define width ADC_WIDTH_BIT_12 // ADC分辨率 12位
#define atten ADC_ATTEN_DB_11  // ADC衰减   11 dB 衰减，输入电压范围为 0-3.3V。
#define unit ADC_UNIT_1        // ADC1
#define NO_OF_SAMPLES 128      // 采样次数, 目的: 多次采样, 滤波

/**
 * @description: ADC初始化
 * @return {无}
 */
void myADC_Init()
{
  adc1_config_width(ADC_WIDTH_BIT_12);                                   // 12位分辨率
  adc1_config_channel_atten(AD_Value1_Channnel, atten);                  // 配置ADC通道
  adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));          // 分配内存
  esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars); // 对ADC特性进行初始化
}

/**
 * @description: 获取传感器的AD值和电压值
 * @param {int16_t} *AD_Value1 传感器的AD值的地址
 * @param {float*} Voltage1    传感器的电压值的地址
 * @return {*}
 */
void myADC_GetAdAndVoltage_Value(int16_t *AD_Value1, float *Voltage1)
{
  uint32_t adc_reading1 = 0;
  for (int i = 0; i < NO_OF_SAMPLES; i++)
  {                                                   // 多次采样, 滤波
    adc_reading1 += adc1_get_raw(AD_Value1_Channnel); // 采集光照值
  }
  adc_reading1 /= NO_OF_SAMPLES; // 得到滤波后的数据

  // esp_adc_cal_raw_to_voltage返回的是mV, 想得到单位V, 除以1000
  *AD_Value1 = (int16_t)adc_reading1;                                       // 转换为int16_t类型
  *Voltage1 = esp_adc_cal_raw_to_voltage(adc_reading1, adc_chars) / 1000.0; // 获取光照电压值
}

int16_t light_AdVal;
float light_Voltage;

static void adc_test(void)
{
  myADC_Init();

  while (1)
  {

    myADC_GetAdAndVoltage_Value(&light_AdVal, &light_Voltage);
    printf("gz adc cal: %d\t gz v: %.2f \n", light_AdVal, light_Voltage);

    sleep(2); // 延时
  }
}

static void adc_example_task(void)
{
  osThreadAttr_t attr;
  int g_taskID;

  attr.name = "adc_test";
  attr.attr_bits = 0U;
  attr.cb_mem = NULL;
  attr.cb_size = 0U;
  attr.stack_mem = NULL;
  attr.stack_size = TASK_STACK_SIZE;
  attr.priority = TASK_PRIO;
  g_taskID = osThreadNew((osThreadFunc_t)adc_test, NULL, &attr);
  if (g_taskID == NULL)
  {
    printf("Failed to create Test GPIO thread!\n");
  }
}

OHOS_APP_RUN(adc_example_task);
